package com.springsecurity.config;

import com.springsecurity.filter.ValidCodeFilter;
import com.springsecurity.service.UserService;
import com.springsecurity.utils.MyAccessDecisionManager;
import com.springsecurity.utils.MyFilterInvocationSecurityMetadataSource;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;

@Configuration
public class WebSecurityConfig {
	@Bean
	PasswordEncoder passwordEncoder(){
		return new BCryptPasswordEncoder();
	}
	/*@Bean
	public UserDetailsService userDetailsService(){
		InMemoryUserDetailsManager manager= new InMemoryUserDetailsManager();
		UserDetails user1 = User.withUsername("admin").password(passwordEncoder().encode("123")).roles("role1", "role2", "role3").build();
		UserDetails user2 = User.withUsername("user1").password(passwordEncoder().encode("123")).roles("role1").build();
		UserDetails user3 = User.withUsername("user2").password(passwordEncoder().encode("123")).roles("role2").build();
		UserDetails user4 = User.withUsername("user3").password(passwordEncoder().encode("123")).roles("role3").build();
		manager.createUser(user1);
		manager.createUser(user2);
		manager.createUser(user3);
		manager.createUser(user4);
		return manager;
	}*/
	@Bean
	public WebSecurityCustomizer webSecurityCustomizer(){
		return (web)->web.ignoring().requestMatchers("/js/**","/css/**","/images/**");
	}
	@Resource
	ValidCodeFilter validCodeFilter;
	@Resource
	UserDetailsService userService;
	@Resource
	MyFilterInvocationSecurityMetadataSource myFilterInvocationSecurityMetadataSource;
	@Resource
	MyAccessDecisionManager myAccessDecisionManager;
	@Bean
	SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
		httpSecurity.addFilterBefore(validCodeFilter, UsernamePasswordAuthenticationFilter.class);
		httpSecurity.authorizeRequests().requestMatchers("/","/index","/validCode").permitAll()//.authorizeHttpRequests()不会动态授权
				/*.requestMatchers("/menu1/**").hasRole("user")
				.requestMatchers("/menu2/**").hasRole("manager")
				.requestMatchers("/menu3/**").hasRole("admin")*/
				.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
					@Override
					public <O extends FilterSecurityInterceptor> O postProcess(O object) {
						object.setSecurityMetadataSource(myFilterInvocationSecurityMetadataSource);
						object.setAccessDecisionManager(myAccessDecisionManager);
						return object;
					}
				})
				.anyRequest().authenticated();
		httpSecurity.formLogin()
				.loginPage("/toLogin")
				.usernameParameter("username")
				.passwordParameter("password")
				.loginProcessingUrl("/login")
				.failureUrl("/toLogin/error")
				.permitAll();
		httpSecurity.logout().logoutSuccessUrl("/index");
		httpSecurity.csrf().disable();
		httpSecurity.rememberMe();
		httpSecurity.exceptionHandling().accessDeniedPage("/errorRole");
		httpSecurity.userDetailsService(userService);
		return httpSecurity.build();
	}
}
